﻿using System;
using System.Globalization;
using System.Linq;
using Comdiv.QWeb.Utils;

namespace Comdiv.QWeb.Binding {
	public class BindTypeConverter {
		public static object DoConvert(string value, Type targettype, object def) {
			if (targettype == typeof (string)) {
				if (string.IsNullOrWhiteSpace(value) && null != def) return def.ToString();
				return value;
			}
			if (null != value && value.GetType().IsAssignableFrom(targettype)) {
				return value;
			}
			if (string.IsNullOrEmpty(value)) {
				if (null != def) {
					if (def.GetType().IsAssignableFrom(targettype)) {
						return def;
					}
					return DoConvert(def.ToString(), targettype, null);
				}
				if (targettype.IsValueType) {
					return Activator.CreateInstance(targettype);
				}
				else {
					return null;
				}
			}
			if (targettype == typeof (int)) {
				return Convert.ToInt32(value);
			}
			if (targettype == typeof (long)) {
				return Convert.ToInt64(value);
			}
			if (targettype == typeof (decimal)) {
				return value.toDecimal();
			}
			if (targettype == typeof (float)) {
				return (float) value.toDecimal();
			}
			if (targettype == typeof (bool)) {
				if (value.Trim() == "1") return true;
				if (value.Trim() == "0") return false;
				return Convert.ToBoolean(value);
			}
			if (targettype == typeof (DateTime)) {
				var ds = value.Trim();
				return DateTime.ParseExact(ds,
				                           new[]
				                           	{
				                           		"dd.MM.yyyy hh:mm:ss",
				                           		"yyyy-MM-dd hh:mm:ss",
				                           		"dd.MM.yyyy", "yyyy-MM-dd",
				                           	},
				                           CultureInfo.InvariantCulture,
				                           DateTimeStyles.AllowWhiteSpaces
					);
			}
			if (targettype.IsEnum) {
				try {
					return Enum.Parse(targettype, value, true);
				}
				catch (Exception ex) {
					return Activator.CreateInstance(targettype);
				}
			}
			if (targettype.IsArray) {
				var raw = value.Split(',');
				var src = raw.Select(x => DoConvert(x, targettype.GetElementType(), null)).ToArray();
				var res = Array.CreateInstance(targettype.GetElementType(), src.Length);
				Array.Copy(src, res, src.Length);
				return res;
			}
			throw new NotSupportedException("cannot convert to " + targettype);
		}
	}
}